using FytSoa.Application.Crm.Param;
using FytSoa.Common.Enum;
using FytSoa.Domain.Crm;
using FytSoa.Common.Param;
using FytSoa.Common.Result;
using FytSoa.Common.Utils;
using FytSoa.Sugar;
using Mapster;
using Masuit.Tools.Systems;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;

namespace FytSoa.Application.Crm;

/// <summary>
/// 项目管理服务接口
/// </summary>
[ApiExplorerSettings(GroupName = "v7")]
public class CrmProjectService : IApplicationService 
{
    private readonly SugarRepository<CrmProject> _thisRepository;
    private readonly SugarRepository<CrmProjectQuote> _quoteRepository;
    private readonly SugarRepository<CrmProjectStage> _stageRepository;
    private readonly CrmOperateLogService _operateLogService;
    public CrmProjectService(SugarRepository<CrmProject> thisRepository
        ,SugarRepository<CrmProjectQuote> quoteRepository
        ,SugarRepository<CrmProjectStage> stageRepository
        ,CrmOperateLogService operateLogService)
    {
        _thisRepository = thisRepository;
        _quoteRepository = quoteRepository;
        _stageRepository = stageRepository;
        _operateLogService = operateLogService;
    }
    
    /// <summary>
    /// 查询所有——分页
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    public async Task<PageResult<CrmProjectDto>> GetPagesAsync(PageParam param)
    {
        var query = await _thisRepository.AsQueryable()
            .WhereIF(param.Id!=0,m=>m.CustomerId==param.Id)
            .WhereIF(param.Type!=0,m=>m.ProjectType==(CrmProjectTypeEnum)param.Type)
            .WhereIF(!string.IsNullOrEmpty(param.Key),m=>m.Name.Contains(param.Key))
            .WhereIF(!string.IsNullOrEmpty(param.Status) && param.Status!="-1",m=>m.Status==(CrmProjectStatusEnum)int.Parse(param.Status))
            .Includes(m=>m.Customer)
            .Includes(m=>m.Contact)
            .Includes(m=>m.ManagerEmployee)
            .OrderByDescending(m=>m.Id)
            .ToPageAsync(param.Page, param.Limit);
        return query.Adapt<PageResult<CrmProjectDto>>();
    }

    /// <summary>
    /// 根据主键查询
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("{id}")]
    public async Task<CrmProjectDto> GetAsync(long id)
    {
        var model = await _thisRepository.AsQueryable()
            .Includes(m=>m.Customer)
            .Includes(m=>m.Contact)
            .Includes(m=>m.ManagerEmployee)
            .FirstAsync(m=>m.Id==id);
        return model.Adapt<CrmProjectDto>();
    }

    /// <summary>
    /// 添加
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    [UnitOfWork]
    public async Task AddAsync(CrmProjectAddParam model)
    {
        if (model.Product.Count > 0)
        {
            model.Project.Amount = model.Quote.Last().Money;
        }
        var toDay = await _thisRepository.CountAsync(m=>m.CreateTime.ToString("yyyy-MM")==DateTime.Now.ToString("yyyy-MM"));
        model.Project.Number = "CPO".ResNumber(toDay, "yyyyMM");
        var projectId=await _thisRepository.InsertReturnSnowflakeIdAsync(model.Project.Adapt<CrmProject>());

        if (model.ProjectStage.Count>0)
        {
            foreach (var item in model.ProjectStage)
            {
                item.ProjectId = projectId;
            }
            await _stageRepository.InsertRangeAsync(model.ProjectStage.Adapt<List<CrmProjectStage>>());
        }

        if (model.Quote.Count>0)
        {
            foreach (var item in model.Quote)
            {
                item.ProjectId = projectId;
            }
            await _quoteRepository.InsertRangeAsync(model.Quote.Adapt<List<CrmProjectQuote>>());
        }
        
        //增加产品
        if (model.Product.Count>0)
        {
            var productRepository = _thisRepository.ChangeRepository<SugarRepository<CrmProjectProduct>>();
            foreach (var item in model.Product)
            {
                item.ProjectId = projectId;
            }

            await productRepository.InsertRangeAsync(model.Product.Adapt<List<CrmProjectProduct>>());
        }
        
        await _operateLogService.AddAsync(new CrmOperateLogDto()
        {
            OperateId = projectId,
            Type = (int)OaOperateEnum.Project,
            Remark = "创建了项目信息"
        });
    }


    /// <summary>
    /// 修改
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    [UnitOfWork]
    public async Task ModifyAsync(CrmProjectAddParam model)
    {
        if (model.Quote.Count>0)
        {
            await _quoteRepository.DeleteAsync(m => m.ProjectId == model.Project.Id);
            foreach (var item in model.Quote)
            {
                item.ProjectId = model.Project.Id;
            }
            await _quoteRepository.InsertRangeAsync(model.Quote.Adapt<List<CrmProjectQuote>>());
            model.Project.Amount = model.Quote.Last().Money;
        }
        await _thisRepository.UpdateAsync(model.Project.Adapt<CrmProject>());
        await _operateLogService.AddAsync(new CrmOperateLogDto()
        {
            OperateId = model.Project.Id,
            Type = (int)OaOperateEnum.Project,
            Remark = "修改了项目信息"
        });
        
        //增加产品
        if (model.Product.Count>0)
        {
            var productRepository = _thisRepository.ChangeRepository<SugarRepository<CrmProjectProduct>>();
            await productRepository.DeleteAsync(m => m.ProjectId == model.Project.Id);
            foreach (var item in model.Product)
            {
                item.ProjectId = model.Project.Id;
            }

            await productRepository.InsertRangeAsync(model.Product.Adapt<List<CrmProjectProduct>>());
        }
        
        foreach (var item in model.ProjectStage)
        {
            item.ProjectId = model.Project.Id;
        }
        var stageList = await _stageRepository.GetListAsync(m => m.ProjectId == model.Project.Id);
        if (stageList.Count != 0) 
        {
            var oldStageIdArr = stageList.Select(m => m.Id).ToList();
            var newStageIdArr = model.ProjectStage.Select(m => m.Id).ToList();
            if (newStageIdArr.All(p => oldStageIdArr.Any(r => r.Equals(p))) && newStageIdArr.Count == oldStageIdArr.Count)
            {
                await _stageRepository.UpdateRangeAsync(model.ProjectStage.Adapt<List<CrmProjectStage>>());
                return;
            }

            var anyIds = oldStageIdArr.Where(m => newStageIdArr.Contains(m)).ToList();
            if (anyIds.Count>0)
            {
                //修改已存在
                var editList = model.ProjectStage.Where(m => anyIds.Contains(m.Id)).ToList();
                await _stageRepository.UpdateRangeAsync(editList.Adapt<List<CrmProjectStage>>());
            }
           
            //差异
            var difference = oldStageIdArr.Except(newStageIdArr).ToList();
            //判断差异是否在数据库里面的，如果存在，则删除
            var delIds=difference.Where(m => oldStageIdArr.Contains(m)).ToList();
            if (delIds.Count>0)
            {
                await _stageRepository.DeleteAsync(m => delIds.Contains(m.Id));
            }
            
            // 判断差异不存在数据库里面的，则添加
            var addIds=newStageIdArr.Where(m => m==0).ToList();
            {
                var addList = model.ProjectStage.Where(m => addIds.Contains(m.Id)).ToList();
                await _stageRepository.InsertRangeAsync(addList.Adapt<List<CrmProjectStage>>());
            }
        }
        else
        {
            await _stageRepository.InsertRangeAsync(model.ProjectStage.Adapt<List<CrmProjectStage>>());
        }
    }

    /// <summary>
    /// 变更项目状态
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    public async Task ModifyStatusAsync(CrmProjectStatusParam model)
    {
        await _thisRepository.UpdateAsync(m => new CrmProject()
        {
            Status = model.Status
        },m=>model.Ids.Contains(m.Id));
        var stageList = await _stageRepository.GetListAsync(m => model.Ids.Contains(m.ProjectId));
        var upStageList = new List<long>();
        foreach (var item in model.Ids)
        {
            var stageModel = stageList.Where(m => m.ProjectId == item).OrderBy(m=>m.Id).First();
            if (stageModel!=null)
            {
                upStageList.Add(stageModel.Id);
            }
            await _operateLogService.AddAsync(new CrmOperateLogDto()
            {
                OperateId = item,
                Type = (int)OaOperateEnum.Project,
                Remark = "修改了项目状态为："+model.Status.GetDescription()
            });
        }

        if (upStageList.Count>0)
        {
            await _stageRepository.UpdateAsync(m => new CrmProjectStage()
            {
                Status = true
            }, m => upStageList.Contains(m.Id));
        }
        
    }
    

    /// <summary>
    /// 变更商机状态
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    public async Task ModifyOpportunityStatusAsync(CrmProjectOpportunityParam model)
    {
        if (model.Status==CrmOpportunityStatusEnum.Winning)
        {
            var quoteModel = await _quoteRepository.GetFirstAsync(m => m.ProjectId == model.Id,m=>m.Id);
            await _thisRepository.UpdateAsync(m => new CrmProject()
            {
                OpportunityStatus = model.Status,
                ProjectType = CrmProjectTypeEnum.Project,
                Amount = quoteModel.Money
            },m=>m.Id==model.Id);
        }
        else
        {
            await _thisRepository.UpdateAsync(m => new CrmProject()
            {
                OpportunityStatus = model.Status
            },m=>m.Id==model.Id);
        }
        await _operateLogService.AddAsync(new CrmOperateLogDto()
        {
            OperateId = model.Id,
            Type = (int)OaOperateEnum.Project,
            Remark = "修改了商机状态为："+model.Status.GetDescription()
        });
    }

    /// <summary>
    /// 删除,支持批量
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    [HttpDelete]
    public async Task DeleteAsync([FromBody] List<long> ids)
    {
        await _thisRepository.DeleteAsync(m=>ids.Contains(m.Id));
        await _quoteRepository.DeleteAsync(m=>ids.Contains(m.ProjectId));
    }
}
